#ifdef PSOS
namespace std { }

using namespace std;

#include <string>
#include <locale>
#endif

#include <fstream>
#include <memfs.h>
#include <log.hpp>
#include <timer.h>

#include <scos.h>
#include "sc.h"
#include "globals.h"
#include "scu.h"

extern "C" scu_list_t scus_procs, scus_streams, scus_bufs, scus_ops;

static CLog clg;

#define FindID(list, item) scuListFindItem(list, 4, SCU_VAR_INTEGER, item)

extern "C" void scuStatRead(char *file)
{
  char *element;
  std::ifstream inp(file);
  XMLParser parser(inp);
  Mfs params_fs;
  Mshell params(params_fs);

  abortOnError(STREAM(clg.err.GetStream()), !inp.is_open());
  abortOnError(STREAM(clg.err.GetStream()), params.Import(parser, "/"));

  scuStatInit();

  params.FindInitDirectoryElements("/trace/processors");
  while (!params.FindGetNextElement(&element))
  {
    Mshell proc(params, element);
    char *name;
    int id;
    
    proc.GetContent("id", &id);
    proc.GetContent("name", &name);

    scuStatAddProcessor(id, name);
  }

  params.FindInitDirectoryElements("/trace/streams");
  while (!params.FindGetNextElement(&element))
  {
    Mshell stream(params, element);    
    int id;

    stream.GetContent("id", &id);
    
    scuStatCloseStream(scuStatAddStream(id));
  }

  params.FindInitDirectoryElements("/trace/buffers");
  while (!params.FindGetNextElement(&element))
  {
    Mshell buffer(params, element);    
    int id, stream, proc, counter, size;
    unsigned long int bytes;
    
    buffer.GetContent("id", &id);
    buffer.GetContent("processor", &proc);
    buffer.GetContent("stream", &stream);
    buffer.GetContent("file", &counter);
    buffer.GetContent("size", &size);

    std::ostringstream s;
    s << "/trace/streams/" << stream << "/bytes";
    params.GetContent(s.str().c_str(), &bytes);

    scuStatCloseBuffer(
      scuStatAddBuffer(id, size,
		       (scus_stream_t*)FindID(&scus_streams, stream),
		       (scus_proc_t*)FindID(&scus_procs, proc)),
      counter, bytes);
  }

  params.FindInitDirectoryElements("/trace/operations");
  while (!params.FindGetNextElement(&element))
  {
    Mshell op(params, element);
    scus_op_t *o;
    int id, type, line, proc;
    char *text;
    double time;

    op.GetContent("id", &id);
    op.GetContent("type", &type);
    op.GetContent("line", &line);
    op.GetContent("text", &text);
    op.GetContent("processor", &proc);
    op.GetContent("time", &time);

    o = scuStatAddOperation(id, type, line, text, NULL, 0,
			    (scus_proc_t*)FindID(&scus_procs, proc));

    op.FindInitDirectoryElements("arguments");
    while (!op.FindGetNextElement(&element))
    {
      Mshell arg(op, element);
      scus_arg_t *a;
      int id, type, intent, i, d;
      double f;

      arg.GetContent("id", &id);
      arg.GetContent("type", &type);
      arg.GetContent("intent", &intent);

      a = scuStatOperationAddArgument(o, id, type, intent);
      
      switch (type)
      {      
	case SC_VAR_STREAM:
	  arg.GetContent("i", &i);
	  scuStatDefineArgument(a, FindID(&scus_bufs, i));
	  break;
	case SC_VAR_INTEGER:
	  arg.GetContent("d", &d);
	  scuStatDefineArgument(a, &d);
	  break;
	case SC_VAR_DOUBLE:
	  arg.GetContent("f", &f);
	  scuStatDefineArgument(a, &f);
	  break;
      }
    }

    scuStatCloseOperation(o);
#ifdef PSOS
    tmrSetValueInUs(&o->timer, time);
#else
    tmrSetValueInUs(&o->timer, (unsigned long long int)time);
#endif
  }
}
